﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;

namespace Celeriq.LogReader
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();

			txtFilter.TextChanged += txtFilter_TextChanged;

			var width = lvwFile.Width - 40;

			lvwSummary.Columns.Clear();
			lvwSummary.Columns.Add("Name", width / 2);
			lvwSummary.Columns.Add("Value", width / 2);

			lvwFile.Columns.Clear();
			lvwFile.Columns.Add("Log file", width );
			lvwFile.ItemSelectionChanged += lvwFile_ItemSelectionChanged;

			lvwLog.Columns.Clear();
			lvwLog.Columns.Add("Log time", width / 5);
			lvwLog.Columns.Add("Source", width / 5);
			lvwLog.Columns.Add("Item count", width / 5);
			lvwLog.Columns.Add("Time (ms)", width / 5);
			lvwLog.Columns.Add("Cache hit", width / 5);
			lvwLog.Columns.Add("Url", width / 5);

		}

		private void txtFilter_TextChanged(object sender, EventArgs e)
		{
			if (lvwFile.SelectedItems.Count == 0) return;
			ProcessFile(lvwFile.SelectedItems[0].Tag as string);
		}

		private void lvwFile_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
		{
			this.ProcessFile(e.Item.Tag as string);
		}

		private void cmdFile_Click(object sender, EventArgs e)
		{
			var dialog = new FolderBrowserDialog();
			if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				txtFolder.Text = dialog.SelectedPath;
				this.ProcessFolder(txtFolder.Text);
			}
		}

		private void ProcessFolder(string folderName)
		{
			var files = System.IO.Directory.GetFiles(folderName, "*.query.log").OrderBy(x => x);
			lvwFile.Items.Clear();
			lvwLog.Items.Clear();
			lvwSummary.Items.Clear();

			foreach (var s in files)
			{
				var fi = new FileInfo(s);
				var newItem = lvwFile.Items.Add(fi.Name.Replace(".query.log", string.Empty));
				newItem.Tag = fi.FullName;
			}

		}

		private void ProcessFile(string fileName)
		{
			var urlList = new Dictionary<string, int>();
			long totalTime = 0;
			long cacheHits = 0;
			long totalHits = 0;
			double totalResults = 0;

			lvwLog.Items.Clear();
			using (var sr = File.OpenText(fileName))
			{
				var text = sr.ReadLine();
				while (!sr.EndOfStream)
				{
					if (!string.IsNullOrEmpty(text) && !text.StartsWith("#"))
					{
						var arr = text.Split('\t');
						if (arr.Length == 6)
						{
							//apply filter if need be
							var doProcess = true;
							if (!string.IsNullOrEmpty(txtFilter.Text))
							{
								doProcess = false;
								var farr = txtFilter.Text.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
								foreach (var s1 in arr)
								{
									foreach (var s2 in farr)
									{
										if (s1.Contains(s2))
										{
											doProcess = true;
											break;
										}
									}
								}
							}


							if (doProcess)
							{ 
							var isError = false;

							DateTime logTime;
							if (!DateTime.TryParseExact(arr[0], "yyyy-MM-dd HH:mm:ss.ff", null, System.Globalization.DateTimeStyles.None, out logTime))
								isError = true;

							int time;
							if (!int.TryParse(arr[3], out time))
								isError = true;

							long resultCount;
							if (!long.TryParse(arr[2], out resultCount))
								isError = true;

								if (!isError)
								{
									totalResults += resultCount;
									totalHits++;
									var isCache = (arr[4] == "1");

									if (!isCache)
									{
										totalTime += time;
									}
									else
									{
										cacheHits++;
									}

									if (urlList.ContainsKey(arr[5]))
										urlList[arr[5]]++;
									else
										urlList.Add(arr[5], 1);

									this.AddLogEntry(arr[0], arr[1], resultCount, time, isCache, arr[5]);
								}

							}
						}
					}
					text = sr.ReadLine();
				}
			}

			#region Summary

			lvwSummary.Items.Clear();
			var computedHits = (totalHits - cacheHits);

			AddSummaryItem("Total hits", totalHits.ToString("###,###,###,##0"));
			AddSummaryItem("Unique hits", urlList.Count.ToString("###,###,###,##0"));
			if (computedHits <= 0)
				AddSummaryItem("Average time", "N/A");
			else
				AddSummaryItem("Average time", (totalTime/(totalHits - cacheHits)).ToString("###,###,##0.0") + " ms");

			if (totalHits == 0)
				AddSummaryItem("Average results", "N/A");
			else
				AddSummaryItem("Average results", (totalResults/totalHits).ToString("###,###,###,##0"));

			AddSummaryItem("Cache hits", cacheHits.ToString("###,###,###,##0"));
			if (totalHits == 0)
				AddSummaryItem("Cache/hit ratio", "N/A");
			else
				AddSummaryItem("Cache/hit ratio", ((cacheHits*100.0)/totalHits).ToString("##0.00") + "%");

			#endregion
		}

		private void AddSummaryItem(string name, string value)
		{
			var newItem = new ListViewItem() {Text = name};
			newItem.SubItems.Add(value);
			lvwSummary.Items.Add(newItem);
		}

		private void AddLogEntry(string logTime, string ip, long resultCount, int time, bool isCache, string url)
		{
			var newItem = lvwLog.Items.Add(logTime);
			newItem.SubItems.Add(ip);
			newItem.SubItems.Add(resultCount.ToString("###,###,###,##0"));
			newItem.SubItems.Add(time.ToString("###,###,###,##0"));
			newItem.SubItems.Add(isCache.ToString().ToLower());
			newItem.SubItems.Add(url);
		}
	}
}
